# coding=utf-8
from django.db import transaction
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from MSB_ERP.utils.get_inventory import get_inventory

from financial_info.models import ReceiptItemModel
from warehouse_info.models import SaleDeliverItemModel,SaleDeliverModel

class OnStorageItemSerializer(serializers.ModelSerializer):
    # 出库单中的货品（货品项目）（子项目）

    # 注意：既然只有库存数据没有，那么可以增加一个属性
    cur_inventory = serializers.SerializerMethodField(label='当前仓库中的数量')

    class Meta:
        model = SaleDeliverItemModel
        fields = '__all__'

    def get_cur_inventory(self,obj):
        result = get_inventory(obj.goods.id,obj.warehouse.id)
        return result if result else 0

class OnStorySerializer(serializers.ModelSerializer):
    # 销售出库单（父项目）

    item_list = OnStorageItemSerializer(many=True,required=False) # 出库单中的货品（货品项目）（子项目）

    good_info = serializers.SerializerMethodField(label='商品的信息的描述')

    # 查询当前销售 出库单中已经 收金额
    already_receipt = serializers.SerializerMethodField(help_text='已经收款的金额')

    class Meta:
        model = SaleDeliverModel
        fields = '__all__'

    def get_already_receipt(self, obj:SaleDeliverModel):
        """
        查询当前 销售出库单中已经 收的货款金额
        :param obj: ReceiptItemModel
        :return: 0获取其他的数值
        """

        sum_dict = ReceiptItemModel.objects.filter(deliver_storage_id=obj.id)\
            .exclude(receipt__status='0')\
            .aggregate(sum=Sum('this_money'))
        if sum_dict:
            return sum_dict['sum'] if sum_dict['sum'] else 0
        return 0


    def get_good_info(self,obj): # 产品的名字+描述
        if obj.item_list.all():
            rusult = []
            for item in obj.item_list.all():
                rusult.append(item.name + (item.specification if item.specification else ''))
            return (','.join(rusult))
        return ''

    def create(self, validated_data): # 重写添加函数
        item_list = validated_data.pop('item_list') # 将子项目提取出来
        with transaction.atomic():
            sale_deliver = SaleDeliverModel.objects.create(**validated_data) # 将父项目添加进去
            for item in item_list:
                # 这个是把销售出库单对应的ID传进去
                sdi = SaleDeliverItemModel.objects.create(sale_deliver=sale_deliver,**item)
                # 添加冗余字段
                goods = item.get('goods')
                sdi.specification = goods.specification
                sdi.model_number = goods.model_number
                sdi.number_code = goods.number_code
                sdi.color = goods.color
                sdi.category = goods.category
                sdi.category_name = goods.category.name
                sdi.units = goods.units
                sdi.units_name = goods.units.basic_name
                sdi.save()
        return sale_deliver

    def update(self, instance, validated_data):
        # 判断状态是不是不可更改的属性
        if instance.status != '0':
            raise ValidationError('销售订单已经生效，不可更改')
        else:
            item_list = validated_data.pop('item_list')
            old_list = instance.item_list.all()
            if old_list.exists():
                with transaction.atomic():
                    old_list.delete() # 删除旧数据
                    sale_deliver = SaleDeliverModel.objects.create(**validated_data)  # 将父项目添加进去
                    for item in item_list:
                        # 将子项目添加进去
                        sdi = SaleDeliverItemModel.objects.create(sale_deliver=sale_deliver, **item)
                        # 添加冗余字段
                        goods = item.get('goods')
                        sdi.specification = goods.specification
                        sdi.model_number = goods.model_number
                        sdi.number_code = goods.number_code
                        sdi.color = goods.color
                        sdi.category = goods.category
                        sdi.category_name = goods.category.name
                        sdi.units = goods.units
                        sdi.units_name = goods.units.basic_name
                        sdi.save()
            return sale_deliver























